<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>xeokit BIM Viewer</title>
    <link rel="stylesheet" href="./viewer/bimviewer/fontawesome-free-5.11.2-web/css/all.min.css" type="text/css"/>
    <link rel="stylesheet" href="../viewer/bimviewer/xeokit-bim-viewer.css" type="text/css"/>
    <link rel="stylesheet" href="./viewer/bimviewer/style.css"/>
</head>

<body>
<input type="checkbox" id="explorer_toggle"/>
<label for="explorer_toggle" class="explorer_toggle_label xeokit-btn fas fa-2x fa-sitemap"
       data-tippy-content="Toggle explorer panel"></label>
<div id="myExplorer"></div>
<div id="myToolbar"></div>
<div id="myViewer">
    <canvas id="myCanvas"></canvas>
    <canvas id="myNavCubeCanvas"></canvas>
</div>
</body>

<!-- App tooltips libraries-->
<script src="./viewer/bimviewer/popper.js"></script>
<script src="./viewer/bimviewer/tippy.js"></script>

<script type="module">

    // Set up application

    import {Server, BIMViewer} from "../viewer/bimviewer/xeokit-bim-viewer.es.js";

    window.onload = function () {

        const requestParams = getRequestParams();

        // Project to load into the viewer
        const projectId = requestParams.projectId;
        if (!projectId) {
            return;
        }

        // Open the explorer tab?
        const openExplorer = requestParams.openExplorer;
        setExplorerOpen(openExplorer === "true");

        const enableEditModels = (requestParams.enableEditModels === "true");

        // Server client will load data from the file systems
        const server = new Server({
            dataDir: "./data"
        });

        // Create  BIMViewer that loads data via the Server
        const bimViewer = new BIMViewer(server, {
            canvasElement: document.getElementById("myCanvas"), // WebGL canvas
            explorerElement: document.getElementById("myExplorer"), // Left panel
            toolbarElement: document.getElementById("myToolbar"), // Toolbar
            navCubeCanvasElement: document.getElementById("myNavCubeCanvas"),
            busyModelBackdropElement: document.getElementById("myViewer"),
            enableEditModels: enableEditModels

        });

        // Create tooltips on various HTML elements created by BIMViewer
        tippy('[data-tippy-content]', {
            appendTo: "parent",
            zIndex: 100000
        });

        // Configure our viewer
        bimViewer.setConfigs({});

        // Log info on whatever objects we click with the BIMViewer's Query tool
        bimViewer.on("queryPicked", (event) => {
            console.log("queryPicked: " + JSON.stringify(event, null, "\t"));
        });

        bimViewer.on("addModel", (event) => { // "Add" selected in Models tab's context menu
            console.log("addModel: " + JSON.stringify(event, null, "\t"));
        });

        bimViewer.on("editModel", (event) => { // "Edit" selected in Models tab's context menu
            console.log("editModel: " + JSON.stringify(event, null, "\t"));
        });

        bimViewer.on("deleteModel", (event) => { // "Delete" selected in Models tab's context menu
            console.log("deleteModel: " + JSON.stringify(event, null, "\t"));
        });

        //--------------------------------------------------------------------------------------------------------------
        // Process page request params, which set up initial viewer state
        //--------------------------------------------------------------------------------------------------------------

        // Viewer configurations
        const viewerConfigs = requestParams.configs;
        if (viewerConfigs) {
            const configNameVals = viewerConfigs.split(",");
            for (let i = 0, len = configNameVals.length; i < len; i++) {
                const configNameValStr = configNameVals[i];
                const configNameVal = configNameValStr.split(":");
                const configName = configNameVal[0];
                const configVal = configNameVal[1];
                bimViewer.setConfig(configName, configVal);
            }
        }

        // Load a project
        bimViewer.loadProject(projectId, () => {

                // The project may load one or models initially.

                // Withe request params, we can also specify:
                //  - models to load
                // - explorer tab to open


                const modelId = requestParams.modelId;
                if (modelId) {
                    bimViewer.loadModel(modelId);
                }

                const tab = requestParams.tab;
                if (tab) {
                    bimViewer.openTab(tab);
                }

                //
                window.setInterval((function () {
                    var lastHash = "";
                    return function () {
                        const currentHash = window.location.hash;
                        if (currentHash !== lastHash) {
                            parseHashParams();
                            lastHash = currentHash;
                        }
                    };
                })(), 200);
            },
            (errorMsg) => {
                console.error(errorMsg);
            });

        function getRequestParams() {
            var vars = {};
            window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (m, key, value) => {
                vars[key] = value;
            });
            return vars;
        }

        function parseHashParams() {
            const params = getHashParams();
            const actionsStr = params.actions;
            if (!actionsStr) {
                return;
            }
            const actions = actionsStr.split(",");
            if (actions.length === 0) {
                return;
            }
            for (var i = 0, len = actions.length; i < len; i++) {
                const action = actions[i];
                switch (action) {
                    case "focusObject":
                        const objectId = params.objectId;
                        if (!objectId) {
                            console.error("Param expected for `focusObject` action: 'objectId'");
                            break;
                        }
                        bimViewer.setAllObjectsSelected(false);
                        bimViewer.setObjectsSelected([objectId], true);
                        bimViewer.flyToObject(objectId, () => {
                            // FIXME: Showing objects in tabs involves scrolling the HTML within the tabs - disable until we know how to scroll the correct DOM element. Otherwise, that function works OK

                            // bimViewer.showObjectInObjectsTab(objectId);
                            // bimViewer.showObjectInClassesTab(objectId);
                            // bimViewer.showObjectInStoreysTab(objectId);
                        });
                        break;
                    case "focusObjects":
                        const objectIds = params.objectIds;
                        if (!objectIds) {
                            console.error("Param expected for `focusObjects` action: 'objectIds'");
                            break;
                        }
                        const objectIdArray = objectIds.split(",");
                        bimViewer.setAllObjectsSelected(false);
                        bimViewer.setObjectsSelected(objectIdArray, true);
                        bimViewer.viewFitObjects(objectIdArray, () => {
                        });
                        break;
                    case "clearFocusObjects":
                        bimViewer.setAllObjectsSelected(false);
                        bimViewer.viewFitAll();
                        // TODO: view fit nothing?
                        break;
                    case "openTab":
                        const tabId = params.tabId;
                        if (!tabId) {
                            console.error("Param expected for `openTab` action: 'tabId'");
                            break;
                        }
                        bimViewer.openTab(tabId);
                        break;
                    default:
                        console.error("Action not supported: '" + action + "'");
                        break;
                }
            }
        }

        function getHashParams() {
            const hashParams = {};
            let e;
            const a = /\+/g;  // Regex for replacing addition symbol with a space
            const r = /([^&;=]+)=?([^&;]*)/g;
            const d = function (s) {
                return decodeURIComponent(s.replace(a, " "));
            };
            const q = window.location.hash.substring(1);
            while (e = r.exec(q)) {
                hashParams[d(e[1])] = d(e[2]);
            }
            return hashParams;
        }

        function setExplorerOpen(explorerOpen) {
            const toggle = document.getElementById("explorer_toggle");
            if (toggle) {
                toggle.checked = explorerOpen;
            }
        }

        window.bimViewer = bimViewer; // For debugging
    };


</script>

</html>
